import json
from datetime import datetime, date, time
from decimal import Decimal
from typing import Any, Dict, List, Optional, Union, Iterable, Set


class SQLAlchemySerializer:
    """
    智能SQLAlchemy ORM对象序列化工具
    自动判断输入是单个对象或集合，统一使用serialize()方法
    """

    DEFAULT_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
    DEFAULT_DATE_FORMAT = "%Y-%m-%d"
    DEFAULT_TIME_FORMAT = "%H:%M:%S"

    def __init__(self,
                 datetime_format: str = DEFAULT_DATETIME_FORMAT,
                 date_format: str = DEFAULT_DATE_FORMAT,
                 time_format: str = DEFAULT_TIME_FORMAT,
                 decimal_places: int = 2,
                 exclude_fields: Optional[Set[str]] = None):
        """
        初始化序列化器

        Args:
            datetime_format: 日期时间格式
            date_format: 日期格式
            time_format: 时间格式
            decimal_places: 小数位数
            exclude_fields: 要排除的字段集合
        """
        self.datetime_format = datetime_format
        self.date_format = date_format
        self.time_format = time_format
        self.decimal_places = decimal_places
        self.exclude_fields = exclude_fields or set()

    def serialize(self, obj: Any) -> Union[Dict, List[Dict], None]:
        """
        智能序列化：自动判断输入类型（单个对象或集合）

        Args:
            obj: SQLAlchemy ORM对象或对象列表

        Returns:
            序列化后的字典或字典列表，或None
        """
        if obj is None:
            return None

        # 检测是否为可迭代对象（但不是字符串）
        if (isinstance(obj, Iterable) and
                not isinstance(obj, (str, bytes, bytearray)) and
                not hasattr(obj, '__sa_instance_state__')):  # 确保不是ORM对象本身
            return self._serialize_collection(obj)

        # 单个对象处理
        return self._serialize_object(obj)

    def _serialize_object(self, obj: Any) -> Optional[Dict]:
        """序列化单个SQLAlchemy对象"""
        if obj is None:
            return None

        try:
            # 只获取表中的实际列（避免触发延迟加载）
            result = {}
            for c in obj.__table__.columns:
                if c.name in self.exclude_fields:
                    continue
                value = getattr(obj, c.name)
                result[c.name] = self._format_value(value)
            return result
        except AttributeError:
            # 可能不是SQLAlchemy对象，尝试基本序列化
            if hasattr(obj, '__dict__'):
                return {k: self._format_value(v) for k, v in obj.__dict__.items()
                        if not k.startswith('_') and k not in self.exclude_fields}
            return None

    def _serialize_collection(self, obj_list: Iterable) -> List[Dict]:
        """序列化对象集合"""
        return [self._serialize_object(item) for item in obj_list if item is not None]

    def _format_value(self, value: Any) -> Any:
        """格式化值，处理特殊类型"""
        if value is None:
            return None

        # 日期时间处理
        if isinstance(value, datetime):
            return value.strftime(self.datetime_format)
        elif isinstance(value, date):
            return value.strftime(self.date_format)
        elif isinstance(value, time):
            return value.strftime(self.time_format)

        # 数值处理
        elif isinstance(value, Decimal):
            return round(float(value), self.decimal_places)
        elif isinstance(value, float):
            return round(value, self.decimal_places)

        # 布尔值处理
        elif isinstance(value, bool):
            return value

        # JSON序列化支持
        elif isinstance(value, (list, dict)):
            return value

        # 其他类型直接返回
        return value


# 创建全局单例
serializer = SQLAlchemySerializer()